from typing import List, Any
import os
import xlwt
from xmindparser import xmind_to_dict


def resolve_path(node_dict: dict, result_list: List[str], parent_title: str) -> None:
    """
    通过递归方式提取XMind中每个主题路径
    :param node_dict: 当前处理的节点字典
    :param result_list: 存储结果的列表
    :param parent_title: 父节点路径
    """
    # 处理当前节点标题，去除首尾空格
    current_title = node_dict["title"].strip()
    # 拼接完整路径
    full_title = f"{parent_title}\t{current_title}" if parent_title else current_title

    # 如果是叶子节点（无子主题），则添加到结果列表
    if "topics" not in node_dict:
        result_list.append(full_title)
    else:
        # 递归处理所有子主题
        for child_node in node_dict["topics"]:
            resolve_path(child_node, result_list, full_title)


def xmind_to_excel(xmind_topic_list: List[dict], output_excel_path: str) -> None:
    """
    将XMind主题列表转换为Excel格式
    :param xmind_topic_list: XMind主题列表
    :param output_excel_path: 输出Excel文件路径
    """
    # 创建工作簿和工作表
    workbook = xlwt.Workbook(encoding='utf-8')
    worksheet = workbook.add_sheet("测试用例", cell_overwrite_ok=True)

    # 设置固定表头
    fixed_headers = ["主模块", "子模块", "用例编号", "用例标题", "优先级", "前置条件", "操作步骤", "预期结果", "实际结果",
                     "等级", "备注", "状态", "测试执行人", "执行时间"]
    for col_index, header in enumerate(fixed_headers):
        worksheet.write(0, col_index, header)

    # 行计数器
    row_counter = 0

    # 处理每个顶级主题（模块）
    for module_index, module_topic in enumerate(xmind_topic_list, 1):
        module_name = module_topic["title"].strip()

        # 获取该模块下的所有测试用例
        test_case_topics = module_topic.get("topics", [])

        # 处理每个测试用例
        for case_index, case_topic in enumerate(test_case_topics, 1):
            case_title = case_topic["title"].strip()
            case_path = f"{module_name}\t{case_title}"

            # 初始化用例信息
            case_info = {
                "优先级": "P3",  # 默认优先级
                "前置条件": "",
                "测试数据": "",
                "测试步骤": "",
                "预期结果": "",
                "用例类型": "功能测试"  # 默认用例类型
            }

            # 解析用例的子主题
            steps = []
            for step_topic in case_topic.get("topics", []):
                step_title = step_topic["title"].strip()

                # 根据标题识别特殊字段
                if step_title.startswith("优先级:"):
                    case_info["优先级"] = step_title.split(":", 1)[1].strip()
                elif step_title.startswith("前置条件:"):
                    case_info["前置条件"] = step_title.split(":", 1)[1].strip()
                elif step_title.startswith("测试数据:"):
                    case_info["测试数据"] = step_title.split(":", 1)[1].strip()
                elif step_title.startswith("预期结果:"):
                    case_info["预期结果"] = step_title.split(":", 1)[1].strip()
                elif step_title.startswith("用例类型:"):
                    case_info["用例类型"] = step_title.split(":", 1)[1].strip()
                else:
                    # 普通测试步骤
                    steps.append(step_title)

            # 合并测试步骤
            case_info["测试步骤"] = "\n".join([f"{i + 1}. {step}" for i, step in enumerate(steps)])

            # 生成用例编号
            case_id = f"{module_index:02d}-{case_index:03d}"

            # 写入用例信息到Excel
            row_counter += 1
            worksheet.write(row_counter, 0, case_id)  # 用例编号
            worksheet.write(row_counter, 1, module_name)  # 所属模块
            worksheet.write(row_counter, 2, case_title)  # 用例标题

            # 写入其他字段
            for col_index, field in enumerate(["优先级", "前置条件", "测试数据", "测试步骤", "预期结果", "用例类型"],
                                              3):
                worksheet.write(row_counter, col_index, case_info[field])

    # 保存Excel文件
    workbook.save(output_excel_path)
    print(f"转换完成，文件已保存至: {output_excel_path}")


def run(xmind_file_path: str) -> None:
    """
    执行XMind到Excel的转换
    :param xmind_file_path: XMind文件路径
    """
    # 检查文件是否存在
    if not os.path.exists(xmind_file_path):
        raise FileNotFoundError(f"指定的XMind文件不存在: {xmind_file_path}")

    # 解析XMind文件
    try:
        xmind_data = xmind_to_dict(xmind_file_path)
    except Exception as e:
        raise Exception(f"解析XMind文件失败: {str(e)}")

    # 提取根主题下的所有子主题
    root_topic = xmind_data[0]['topic']
    if 'topics' not in root_topic:
        print("XMind文件中未发现主题内容")
        return

    # 生成输出文件路径（与输入文件同目录，同名但扩展名改为.xlsx）
    file_dir, file_name = os.path.split(xmind_file_path)
    file_base_name = os.path.splitext(file_name)[0]
    output_excel_path = os.path.join(file_dir, f"{file_base_name}.xlsx")

    # 执行转换
    xmind_to_excel(root_topic['topics'], output_excel_path)


# 使用说明
USAGE_INSTRUCTIONS = """
XMind测试用例转换工具使用说明：

1. 环境准备：
   - 安装Python 3.6+
   - 安装依赖库：
     pip install xlwt xmindparser

2. XMind文件规范：
   - 使用XMind 8或以上版本创建思维导图
   - 根主题下的一级子主题作为模块名称
   - 模块下的二级子主题作为测试用例标题
   - 测试用例下的子主题支持以下特殊格式：
     * 优先级:P1 - 设置用例优先级
     * 前置条件:系统已登录 - 设置前置条件
     * 测试数据:用户名=admin,密码=123456 - 设置测试数据
     * 预期结果:页面显示正确 - 设置预期结果
     * 用例类型:接口测试 - 设置用例类型
     * 普通文本将作为测试步骤

3. 使用方法：
   - 修改下面的xmind_file_path变量，指向你的XMind文件
   - 运行脚本，将自动生成对应的Excel文件
   - 生成的Excel文件将保存在与XMind文件相同的目录下

4. 示例XMind结构：
   [用户管理模块]
   ├─ [用户登录成功]
   │  ├─ 优先级:P1
   │  ├─ 前置条件:系统已启动
   │  ├─ 测试数据:用户名=admin,密码=123456
   │  ├─ 输入正确的用户名和密码
   │  ├─ 点击登录按钮
   │  └─ 预期结果:成功登录，跳转到首页
   └─ [用户登录失败-密码错误]
      ├─ 优先级:P2
      ├─ 前置条件:系统已启动
      ├─ 测试数据:用户名=admin,密码=wrong
      ├─ 输入正确的用户名和错误的密码
      ├─ 点击登录按钮
      └─ 预期结果:提示"密码错误"
"""

if __name__ == '__main__':
    print(USAGE_INSTRUCTIONS)

    # 请修改此处为你的XMind文件路径
    xmind_file_path = r"E:\面试\xmind\智能手表.xmind"

    # 检查是否已设置文件路径
    if not xmind_file_path:
        print("错误：请设置XMind文件路径！")
    else:
        try:
            run(xmind_file_path)
        except Exception as e:
            print(f"转换过程中发生错误: {str(e)}")